<template>
  <view class="three-content">
    <canvas class='scene' id="scene" canvas-id="scene" type="webgl" :style="'width:100%; height:'+mSceneHeight+'px;'"
      @touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd"></canvas>
  </view>
</template>

<script>
  import {
    createScopedThreejs
  } from 'threejs-miniprogram'
  import GLTF from '../../lib/GLTFLoader.js'
  export default {
    name: "threeContent",
    data() {
      return {
        touchStartX: 0,
        touchStartY: 0,
        touchStartTime: 0,
        initialPinchDistance: 0,
        initialCameraDistance: 0,
        isTouching: false,
        lastCenterX: null,
        lastCenterY: null,
        module: null,
        camera: null,
        scene: null,
        THREE: null,
        // mSceneWidth: uni.getWindowInfo().windowWidth,
        mSceneHeight: 200,
        worldFocus: null,
        mCanvasId: null
      };
    },
    methods: {
      prepareModel(model) {
        // 模型标准化处理
        model.traverse((child) => {
          console.log(child.isMesh)
          if (child.isMesh) {
            // 工业材质增强
            child.material.metalness = 0.8;
            child.material.roughness = 0.2;
            child.castShadow = true
          }
        });
        // 统一缩放和定位
        model.position.set(0, -3.3, 0);
        model.scale.set(0.04, 0.04, 0.04);
        return model
      },
      initAnimationSystem(THREE, gltf, scene, renderer, camera, canvas) {
        // 动画混合器初始化
        const mixer = new THREE.AnimationMixer(gltf.scene);
        if (gltf.animations?.length) {
          const action = mixer.clipAction(gltf.animations[0]);
          action.play();
        }
        // 工业级渲染循环
        const clock = new THREE.Clock();
        const animate = () => {
          const delta = clock.getDelta();
          // 更新动画
          if (mixer) mixer.update(delta)
          // 实时渲染
          if (scene.children.length > 0) {
            // renderer.physicallyCorrectLights = true;
            // renderer.toneMapping = THREE.ACESFilmicToneMapping;
            // renderer.outputColorSpace = THREE.SRGBColorSpace;
            renderer.render(scene, camera);

          }
          // 使用小程序专用动画API
          canvas.requestAnimationFrame(animate);
        };
        animate();
        // 保存引用以便销毁
        this.appContext = {
          mixer,
          animate
        };
      },
      touchStart(e) {
        console.log(e)
        // 记录初始触摸信息
        this.touchStartX = e.touches[0].clientX;
        this.touchStartY = e.touches[0].clientY;
        this.touchStartTime = Date.now()
        // 多点触控检测
        if (e.touches.length >= 2) {
          const touch1 = e.touches[0];
          const touch2 = e.touches[1];
          this.initialPinchDistance = Math.sqrt(
            Math.pow(touch2.clientX - touch1.clientX, 2) + Math.pow(touch2.clientY - touch1.clientY, 2));
          this.initialCameraDistance = this.camera.position.length();
        }
        this.isTouching = true

      },
      touchMove(e) {
        console.log(e, this.isTouching)
        if (!this.isTouching || !this.camera || !this.scene) return;
        const currentX = e.touches[0].clientX;
        const currentY = e.touches[0].clientY;
        const deltaX = currentX - this.touchStartX;
        const deltaY = currentY - this.touchStartY;
        // 单指旋转操作
        if (e.touches.length === 1) {
          const rotationSpeed = 0.005;
          // 水平移动控制Y轴旋转
          this.model.rotation.y += deltaX * rotationSpeed;
          // 垂直移动控制X轴旋转
          this.model.rotation.x += deltaY * rotationSpeed;
          // 限制X轴旋转角度
          this.model.rotation.x = Math.max(
            -Math.PI / 2, Math.min(Math.PI / 2, this.model.rotation.x));
          this.touchStartX = currentX;
          this.touchStartY = currentY
        }
        // 双指缩放和平移操作
        if (e.touches.length >= 2) {
          const touch1 = e.touches[0];
          const touch2 = e.touches[1];
          // 计算当前两指距离
          const currentPinchDistance = Math.sqrt(
            Math.pow(touch2.clientX - touch1.clientX, 2) + Math.pow(touch2.clientY - touch1.clientY, 2));
          // 缩放操作
          const pinchRatio = currentPinchDistance / this.initialPinchDistance;
          const zoomSpeed = 0.5;
          const targetDistance = this.initialCameraDistance / pinchRatio;
          // 平滑缩放
          this.camera.position.normalize().multiplyScalar(targetDistance);
          this.camera.lookAt(this.scene.position);
          this.initialPinchDistance = currentPinchDistance;
          this.initialCameraDistance = targetDistance;
          // 平移操作-计算双指中心点移动
          const currentCenterX = (touch1.clientX + touch2.clientX) / 2;
          const currentCenterY = (touch1.clientY + touch2.clientY) / 2;
          if (this.lastCenterX && this.lastCenterY) {
            const panDeltaX = currentCenterX - this.lastCenterX;
            const panDeltaY = currentCenterX - this.lastCenterY;
            const panSpeed = 0.01;
            const panVector = new this.THREE.Vector3(
              -panDeltaX * panSpeed,
              panDeltaY * panSpeed,
              0);
            // 根据相机方向调整平移向量
            panVector.applyQuaternion(this.camera.quaternion);
            this.model.position.add(panVector)
          }
          this.lastCenterX = currentCenterX;
          this.lastCenterY = currentCenterY;
        }

      },
      touchEnd(e) {
        this.isTouching = false;
        this.lastCenterX = null;
        this.lastCenterY = null;
      }
    },

    mounted() {
      uni.createSelectorQuery().in(this).select('#scene').node().exec((res) => {
        if (res[0] && res[0].node) {
          const canvas = res[0].node
          const THREE = createScopedThreejs(canvas)
          this.mCanvasId = res[0].node.id;
          const renderer = new THREE.WebGLRenderer({
            canvas: canvas,
            antialias: true,
            context: canvas.getContext('webgl')
          });
          // 创建场景
          const scene = new THREE.Scene();
          // 创建相机
          const camera = new THREE.PerspectiveCamera(75, canvas.width / canvas.height, 0.1, 1000);
          camera.position.set(0, 0, 5);
          camera.lookAt(0, 0, 0);
          // 添加光源
          const ambientLight = new THREE.AmbientLight(0x404040);
          scene.add(ambientLight);
          const hemisphereLight = new THREE.HemisphereLight(0xffffbb, 0x080820, 1);
          scene.add(hemisphereLight)
          const directionalLight = new THREE.DirectionalLight(0xffffff, 1.5);
          directionalLight.position.set(5, 10, 7);
          directionalLight.castShadow = true
          scene.add(directionalLight);

          //加载3D模型
          let GLTFloader = GLTF(THREE)
          const loader = new GLTFloader();
          loader.load(
            "https://models.vectquant.com/3dmodels/downloadable/scene.gltf",
            (gltf) => {
              // 模型预处理
              const model = this.prepareModel(gltf.scene);
              scene.add(model)

              // 保存引用
              this.model = model;
              this.camera = camera;
              this.scene = scene;
              this.THREE = THREE;
              // 启动数字孪生动画系统
              this.initAnimationSystem(THREE, gltf, scene, renderer, camera, canvas);
              // 移除进度条
              // progressBar.remove()
              console.log("模型加载成功", gltf)
            },
            (xhr) => {
              // 加载进度反馈
              const percent = (xhr.loaded / xhr.total * 100).toFixed();
              // progressBar.update(percent);
            },
            (error) => {
              console.error("加载失败：", error);
              // progressBar.showError();
            }
          );
        } else {
          console.error('未找到canvas节点')
        }
      })
    }
  }
</script>

<style lang="scss">
  .three-content {
    // width: 100%;
    height: 200px;

    // /* 或具体数值 */
    // min-height: 100px;
    // display: block;

  }
</style>